#!/usr/bin/env python
# -*- coding:utf8 -*-
# uncompyle6 version 2.15.1
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.10 (default, Jul  1 2017, 13:36:56) 
# [GCC 4.4.6 20110731 (Red Hat 4.4.6-4)]
# Embedded file name: ./esb/common/base_utils.py
# Compiled at: 2017-11-16 15:44:28
"""
Tencent is pleased to support the open source community by making 蓝鲸智云(BlueKing) available.
Copyright (C) 2017 THL A29 Limited, a Tencent company. All rights reserved.
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at http://opensource.org/licenses/MIT
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and limitations under the License.
"""
import re, json, datetime, decimal, string, random, hashlib
from common.errors import error_codes
from common.log import logger

class CustomJSONEncoder(json.JSONEncoder):
    """
    JSONEncoder subclass that knows how to encode date/time and decimal types.
    And process the smart place name object
    """
    date_format = '%Y-%m-%d'
    time_format = '%H:%M:%S'

    def default(self, o):
        if isinstance(o, datetime.datetime):
            return o.strftime('%s %s' % (self.date_format, self.time_format))
        if isinstance(o, datetime.date):
            return o.strftime(self.date_format)
        if isinstance(o, datetime.time):
            return o.strftime(self.time_format)
        if isinstance(o, decimal.Decimal):
            return str(o)
        return super(CustomJSONEncoder, self).default(o)


def jsonize(d):
    return json.dumps(d, cls=CustomJSONEncoder, ensure_ascii=False)


def str_bool(value):
    """
    Convert string to boolean.
    
        >>> str_bool("0")
        False
        >>> str_bool("1")
        True
        >>> str_bool("true")
        True
        >>> str_bool("false")
        False
    """
    if isinstance(value, basestring):
        value = value.strip()
        if value.lower() in ('0', 'false'):
            return False
    return bool(value)


class FancyDict(dict):

    def __getattr__(self, key):
        try:
            return self[key]
        except KeyError as k:
            raise AttributeError(k)

    def __setattr__(self, key, value):
        self[key] = value

    def __delattr__(self, key):
        try:
            del self[key]
        except KeyError as k:
            raise AttributeError(k)


def smart_lower(value):
    """
        >>> smart_lower('RequestFriendHandler')
        'request_friend_handler'
    """
    result = [
     value[0].lower()]
    for c in value[1:]:
        if c >= 'A' and c <= 'Z':
            result.append('_')
        result.append(c.lower())

    return ('').join(result)


def smart_upper(value):
    """
        >>> smart_upper('request_friend_handler')
        'requestFriendHandler'
    """
    value_list = value.split('_')
    return ('').join((string.capitalize(word) if 1 else word for i, word in enumerate(value_list) if i != 0))


def smart_str(s, encoding='utf-8'):
    """
    转换一个字符串或者unicode为指定的编码
    """
    if isinstance(s, unicode):
        return s.encode(encoding)
    if s and encoding != 'utf-8':
        return s.decode('utf-8', 'ignore').encode(encoding, 'ignore')
    return str(s)


def smart_unicode(s, encoding='utf-8'):
    """
    转换一个字符串或者unicode为unicode
    """
    if isinstance(s, unicode):
        return s
    return s.decode(encoding, 'ignore')


def unique(obj):
    """
    Unique with order
    """
    temp = set()
    return [ x for x in obj if x not in temp and not temp.add(x) ]


def get_not_empty_value(kwargs):
    """
    获取非空数据，去除数据为空字段
    """
    data = {}
    for k, v in kwargs.items():
        if v not in (None, '', [], {}):
            data[k] = v

    return data


UNICODE_ASCII_CHARACTER_SET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

def generate_token(length=30, chars=UNICODE_ASCII_CHARACTER_SET):
    """
    Generates a non-guessable OAuth token
    """
    rand = random.SystemRandom()
    return ('').join((rand.choice(chars) for x in range(length)))


def get_client_ip(request):
    """
    获取远程访问主机的IP地址
    """
    client_ip = request.META.get('HTTP_X_FORWARDED_FOR')
    if not client_ip:
        client_ip = request.META.get('REMOTE_ADDR', '')
    try:
        client_ip = re.findall('[\d.]{7,15}', client_ip)
    except:
        logger.exception('request: %s' % request)
        client_ip = ''
    else:
        client_ip = (';').join(client_ip)

    return client_ip


def get_request_params(request):
    if request.method not in ('GET', 'POST'):
        raise error_codes.COMMON_ERROR.format_prompt(u'请求方法错误，请使用GET或POST请求。', replace=True)
    if request.method == 'GET':
        request_params = dict(request.GET.items())
    else:
        if request.body and request.body.strip().startswith('{'):
            try:
                request_params = json.loads(request.body)
            except:
                logger.exception('request.body should be a json: %s', request.body)
                raise error_codes.COMMON_ERROR.format_prompt(u'请求JSON串格式错误，无法解析。', replace=True)

        else:
            request_params = dict(request.POST.items())
    return request_params


def datetime_format(dt):
    date_format = '%Y-%m-%d'
    time_format = '%H:%M:%S'
    if isinstance(dt, (int, float)):
        dt = datetime.datetime.fromtimestamp(dt)
    if isinstance(dt, datetime.datetime):
        return dt.strftime('%s %s' % (date_format, time_format))
    if isinstance(dt, datetime.date):
        return dt.strftime(date_format)


def get_md5(src):
    m = hashlib.md5()
    m.update(smart_str(src))
    return m.hexdigest()
